﻿using System.Drawing;
using System.Drawing.Drawing2D;
using CC.Yacht.Interfaces;

namespace CC.Yacht.Windows.Forms
{
    // ReSharper disable InconsistentNaming
    public class GDIDiePainter : IDiePainter
    // ReSharper restore InconsistentNaming
    {
        #region Private Fields
        private Color _BorderColor = Color.Black;
        private Color _DieColor = Color.White;
        private Color _ForeColor = Color.Black;
        private Color _LockedBorderColor = Color.Red;
        private Color _LockedDieColor = Color.White;
        private Color _LockedForeColor = Color.Black;
        private int _ScaleMode;
        #endregion

        #region IDiePainter Members
        public void Draw(object canvas, IDie die, Rectangle bounds, int scaleMode, Color borderColor, Color dieColor, Color foreColor, Color lockedBorderColor, Color lockedDieColor, Color lockedForeColor)
        {
            _BorderColor = borderColor;
            _DieColor = dieColor;
            _ForeColor = foreColor;
            _LockedBorderColor = lockedBorderColor;
            _LockedDieColor = lockedDieColor;
            _LockedForeColor = lockedForeColor;
            _ScaleMode = scaleMode;

            Graphics graphics = canvas as Graphics;
            if (graphics != null)
            {
                DrawDie(graphics, die, bounds);
            }
        }
        #endregion

        #region Private Methods
        private void DrawDie(Graphics g, IDie die, Rectangle bounds)
        {
            bounds.Inflate(-1, -1);
            Rectangle dotsRectangle = new Rectangle(bounds.X + 1, bounds.Y + 1, bounds.Width - 1, bounds.Height - 1);
            Rectangle backgroundRectangle = new Rectangle(bounds.X + 1, bounds.Y + 1, bounds.Width - 1, bounds.Height - 1);

            if (die.Locked)
            {
                backgroundRectangle.Height -= 1;
                backgroundRectangle.Width -= 1;
            }

            using (Pen pen = new Pen(new SolidBrush(die.Locked ? _LockedBorderColor : _BorderColor), die.Locked ? 2 : 1))
            {
                g.DrawRectangle(pen, bounds);
            }

            g.FillRectangle(new SolidBrush(die.Locked ? _LockedDieColor : _DieColor), backgroundRectangle);

            if (die.Face != DieFace.None)
            {
                DrawDots(g, die, GetRects((int)die.Face, dotsRectangle));
            }
        }

        private void DrawDot(Graphics g, IDie die, Rectangle r)
        {
            g.SmoothingMode = SmoothingMode.AntiAlias;
            r.Inflate(-_ScaleMode, -_ScaleMode);
            g.FillEllipse(new SolidBrush(die.Locked ? _LockedForeColor : _ForeColor), r);
        }

        private void DrawDots(Graphics g, IDie die, Rectangle[] rects)
        {
            for (int i = 0; i < rects.Length; i++)
            {
                DrawDot(g, die, rects[i]);
            }
        }

        private static Size GetDotSize(Rectangle bounds)
        {
            return new Size(bounds.Width / 3, bounds.Height / 3);
        }

        private static Rectangle GetRectangle(int x, int y, Rectangle bounds)
        {
            return new Rectangle(bounds.X + (bounds.Width*x/3), bounds.Y + (bounds.Height*y/3), GetDotSize(bounds).Width, GetDotSize(bounds).Height);
        }

        private static Rectangle[] GetRects(int value, Rectangle bounds)
        {
            Rectangle[] one = new [] {GetRectangle(1, 1, bounds)};
            Rectangle[] two = new [] {GetRectangle(0, 2, bounds), GetRectangle(2, 0, bounds)};
            Rectangle[] three = new [] {GetRectangle(0, 2, bounds), GetRectangle(1, 1, bounds), GetRectangle(2, 0, bounds)};
            Rectangle[] four = new [] {GetRectangle(0, 0, bounds), GetRectangle(0, 2, bounds), GetRectangle(2, 0, bounds), GetRectangle(2, 2, bounds)};
            Rectangle[] five = new [] {GetRectangle(0, 0, bounds), GetRectangle(1, 1, bounds), GetRectangle(0, 2, bounds), GetRectangle(2, 0, bounds), GetRectangle(2, 2, bounds)};
            Rectangle[] six = new [] {GetRectangle(0, 0, bounds), GetRectangle(0, 1, bounds), GetRectangle(0, 2, bounds), GetRectangle(2, 0, bounds), GetRectangle(2, 1, bounds), GetRectangle(2, 2, bounds)};

            Rectangle[][] rects = { one, two, three, four, five, six };
            
            return rects[value - 1];
        }
        #endregion
    }
}
